moddbfandomcom-20200213-history
OpenGL:Extension
The OpenGL standard allows individual vendors to provide additional functionality through extensions as new technology is created. Extensions may introduce new functions and new constants, and may relax or remove restrictions on existing OpenGL functions. For more information, see the Wikipedia entry for OpenGL Extensions. Loading extensions Loading extensions is a platform dependent task, and relies on a few non-standard API calls to get function pointers to the extension functions. Checking for extensions The first step to using OpenGL extensions is to locate the copy of the header file that advertises the API interfaces for the extensions that you plan to use. sets C preprocessor macros to indicate whether the header advertises the interface of a particular extension or not. For example, the basic supplied with Visual C++ 4.2 has a section reading: /* Extensions */ #define GL_EXT_vertex_array 1 #define GL_WIN_swap_hint 1 #define GL_EXT_bgra 1 #define GL_EXT_paletted_texture 1 #define GL_EXT_clip_disable 1 These macros indicate that the header file advertises the above five extensions. So based on the extension name #defines in , one can write your code so that it can compile in the extension functionality if your compiler environment supports the extension’s interfaces. The next problem is that even though your compiler environment may support the extension’s interface at compile-time, at run-time, the target system where you run your application may not support the extension. In the Win32 environment, different OpenGL drivers can support different OpenGL extensions depending on what the hardware and the vendor’s ICD driver writers implement in thedriver. Assuming that your application thread is made current to an OpenGL rendering context, the following routine can be used to determine at run-time if the OpenGL implementation really supports a particular extension: #include #include int isExtensionSupported(const char *extension) { const GLubyte *extensions = NULL; const GLubyte *start; GLubyte *where, *terminator; /* Extension names should not have spaces. */ where = (GLubyte *) strchr(extension, ' '); if (where || *extension '\0') return 0; extensions = glGetString(GL_EXTENSIONS); /* It takes a bit of care to be fool-proof about parsing the OpenGL extensions string. Don't be fooled by sub-strings, etc. */ start = extensions; for (;;) { where = (GLubyte *) strstr((const char *) start, extension); if (!where) break; terminator = where + strlen(extension); if (where start || *(where - 1) ' ') if (*terminator ' ' || *terminator '\0') return 1; start = terminator; } return 0; } With the isExtensionSupported routine, you can check if the current OpenGL rendering context supports a given OpenGL extension. To make sure that the EXT_bgra extension is supported before using it, you can do the following: /* At context initialization. */ int hasBGRA = isExtensionSupported("GL_EXT_bgra"); /* When trying to use EXT_bgra extension. */ #ifdef GL_EXT_bgra if (hasBGRA) { glDrawPixels(width, height, GL_BGRA_EXT, GL_UNSIGNED_BYTE, pixels); } else #endif { /* No EXT_bgra so bail (or implement software workaround). */ fprintf(stderr, "Needs EXT_bgra extension!\n"); exit(1); } Notice that if the EXT_bgra extension is lacking at either run-time or compile-time, the code above will detect the lack of EXT_bgra support. Sure the code is a bit messy, but the code above works. You can skip the compile-time check if you know what development environment you are using and you do not expect to ever compile with a that does not support the extensions that your application uses. But the run-time check really should be performed since who knows on what system your program ends up getting run on. Loading extensions in Windows First, declare function prototype typedefs that match the extension’s entry points. For example: #ifdef _WIN32 typedef void (APIENTRY * PFNGLPOINTPARAMETERFEXTPROC)(GLenum pname, GLfloat param); typedef void (APIENTRY * PFNGLPOINTPARAMETERFVEXTPROC)(GLenum pname, const GLfloat *params); #endif Your header file may already have these typedefs declared if your defines the GL_EXT_point_parameters macro. Now declare global variables of the type of these function prototype typedefs like this: #ifdef _WIN32 PFNGLPOINTPARAMETERFEXTPROC glPointParameterfEXT; PFNGLPOINTPARAMETERFVEXTPROC glPointParameterfvEXT; #endif Once we use wglGetProcAddress to assign these function variables the address of the OpenGL driver’s extension functions, we can call glPointParameterfEXT and glPointParameterfvEXT as if they were normal functions. You pass wglGetProcAddress the name of the routine as an ASCII string. glPointParameterfEXT = (PFNGLPOINTPARAMETERFEXTPROC) wglGetProcAddress("glPointParameterfEXT"); glPointParameterfvEXT = (PFNGLPOINTPARAMETERFVEXTPROC)wglGetProcAddress("glPointParameterfvEXT"); Be careful because the function returned by wglGetProcAddress is only be guaranteed to work for the OpenGL rendering context that was current when wglGetProcAddress was called. Helper Libraries It is highly recommended that instead of using the above, one use helper libraries that abstract extension loading away. Two such libraries are GLee and Glew. References * OpenGL.org's Extension Page